const Koa = require("koa");
const Router = require("koa-router");
const { koaBody } = require("koa-body");
const shell = require("shelljs");
const fs = require("fs-extra");
const path = require("path");
const crypto = require("crypto");

const app = new Koa();
const router = new Router();

// 配置信息
const config = {
  port: 8000,
  frontendPort: 8080,
  repoUrl: "git@gitee.com:hkaiyue/jira.git", // 替换为你的前端仓库地址
  branch: "main",
  buildPath: path.join(__dirname, "../frontend"),
  deployPath: path.join(__dirname, "../deploy"),
};

// 使用 koa-body 中间件
app.use(koaBody());

// 部署函数
async function deploy(ctx) {
  try {
    console.log("开始部署流程...");

    // 先停止已存在的PM2服务
    console.log("停止已存在的PM2服务...");
    shell.exec('pm2 delete "frontend-static" || true');
    // 添加短暂延迟确保服务完全停止
    await new Promise((resolve) => setTimeout(resolve, 1000));

    // 确保目录存在
    await fs.ensureDir(config.buildPath);
    await fs.ensureDir(config.deployPath);

    // 克隆/拉取代码
    shell.cd(config.buildPath);
    if (!fs.existsSync(path.join(config.buildPath, ".git"))) {
      console.log("克隆仓库...");
      const cloneResult = shell.exec(`git clone ${config.repoUrl} .`);
      if (cloneResult.code !== 0) {
        throw new Error(`Git克隆失败: ${cloneResult.stderr}`);
      }
    } else {
      console.log("拉取最新代码...");
      const pullResult = shell.exec(`git pull origin ${config.branch}`);
      if (pullResult.code !== 0) {
        throw new Error(`Git拉取失败: ${pullResult.stderr}`);
      }
    }

    // 清理之前的安装
    console.log("清理 node_modules...");
    await fs.remove(path.join(config.buildPath, "node_modules"));
    await fs.remove(path.join(config.buildPath, "package-lock.json"));

    // 安装依赖（添加 --ignore-scripts 参数）
    console.log("安装依赖...");
    const installResult = shell.exec(
      "npm install --legacy-peer-deps --ignore-scripts"
    );
    if (installResult.code !== 0) {
      throw new Error(`依赖安装失败: ${installResult.stderr}`);
    }

    // 降级 TypeScript 版本
    console.log("安装兼容的 TypeScript 版本...");
    const typescriptResult = shell.exec(
      "npm install typescript@4.9.5 --legacy-peer-deps"
    );
    if (typescriptResult.code !== 0) {
      throw new Error(`TypeScript 安装失败: ${typescriptResult.stderr}`);
    }

    // 构建项目
    console.log("构建项目...");
    const buildResult = shell.exec("npm run build");
    if (buildResult.code !== 0) {
      throw new Error(`项目构建失败: ${buildResult.stderr}`);
    }

    // 部署到目标目录
    await fs.emptyDir(config.deployPath);
    await fs.copy(path.join(config.buildPath, "build"), config.deployPath);

    // 启动静态服务器
    console.log("启动静态服务器...");
    shell.cd(config.deployPath);
    const pm2Result = shell.exec(
      `pm2 serve ${config.deployPath} ${config.frontendPort} --name "frontend-static" --spa -f`
    );
    if (pm2Result.code !== 0) {
      throw new Error(`PM2启动失败: ${pm2Result.stderr}`);
    }

    ctx.body = {
      success: true,
      message: "部署成功",
    };
  } catch (error) {
    console.error("部署失败:", error);
    ctx.status = 500;
    ctx.body = {
      success: false,
      message: "部署失败",
      error: error.message,
      time: new Date().toISOString(),
    };
  }
}

// webhook 路由
router.post("/webhook", async (ctx) => {
  try {
    // 获取 Gitee webhook 请求头
    const timestamp = ctx.headers["x-gitee-timestamp"];
    const token = ctx.headers["x-gitee-token"];
    const event = ctx.headers["x-gitee-event"];
    console.log("webhook 请求头", ctx.headers);
    // 验证必要的请求头
    if (!timestamp || !token || !event) {
      ctx.status = 400;
      ctx.body = {
        success: false,
        message: `缺少必要的 Gitee Webhook 请求头${timestamp} ${token} ${event}`,
      };
      return;
    }

    // 验证事件类型
    if (event !== "Push Hook") {
      ctx.status = 400;
      ctx.body = {
        success: false,
        message: "不支持的事件类型",
      };
      return;
    }

    console.log("Webhook 验证通过，开始部署...");
    await deploy(ctx);
  } catch (error) {
    console.error("Webhook 处理失败:", error);
    ctx.status = 500;
    ctx.body = {
      success: false,
      message: "Webhook 处理失败",
      error: error.message,
      time: new Date().toISOString(),
    };
  }
});

// 使用 router.get 而不是 app.get
router.get("/deploy", async (ctx) => {
  try {
    console.log("收到部署请求");
    await deploy(ctx);
  } catch (error) {
    console.error("部署请求处理失败:", error);
    ctx.status = 500;
    ctx.body = {
      success: false,
      message: "部署失败",
      error: error.message,
    };
  }
});

// 健康检查路由
router.get("/health", async (ctx) => {
  ctx.body = {
    status: "ok",
    timestamp: new Date().toISOString(),
  };
});

// 错误处理中间件
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    console.error("服务器错误:", err);
    ctx.status = err.status || 500;
    ctx.body = {
      success: false,
      message: err.message || "服务器内部错误",
    };
  }
});

// 注册路由中间件
app.use(router.routes()).use(router.allowedMethods());

// 启动服务器
const server = app.listen(config.port, () => {
  console.log(`CI/CD 服务器运行在端口 ${config.port}`);
  console.log(`前端项目将部署在端口 ${config.frontendPort}`);
});

// 优雅关闭
process.on("SIGTERM", () => {
  console.log("收到 SIGTERM 信号，准备关闭服务器...");
  server.close(() => {
    console.log("服务器已关闭");
    process.exit(0);
  });
});
